﻿using Adnc.Application.Shared.Enum;
using Adnc.Application.Shared.Services;
using Adnc.Infra.Caching;
using Adnc.Infra.EventBus;
using Adnc.Infra.Helper;
using Adnc.Infra.IRepositories;
using Adnc.Shared.Events;
using Adnc.Shared.RpcServices.Services;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WYT.Pay.Application.Contracts.Dtos.Payment;
using WYT.Pay.Application.Contracts.Services;
using WYT.Pay.Repository.Entities;

namespace WYT.Pay.Application.Services
{
    public class PaymentAppService : AbstractAppService, IPaymentAppService
    {
        private readonly IEfRepository<PaymentOrder> _orderPayRepository;

        private readonly IConfiguration _config;

        private readonly IDistributedLocker _locker;

        private readonly IEventPublisher _eventPublisher;

        private readonly IUserRpcService _userRpcService;

        public PaymentAppService(
            IEfRepository<PaymentOrder> orderPayRepository
            , IDistributedLocker locker
            , IEventPublisher eventPublisher
            , IUserRpcService userRpcService
            , IConfiguration config)
        {
            _orderPayRepository = orderPayRepository;
            _config = config;
            _eventPublisher = eventPublisher;
            _userRpcService = userRpcService;
            _locker = locker;
        }

        /// <summary>
        /// 订单支付处理
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<AppSrvResult> OrderPayHandle(OrderPayDto input)
        {
            var order = await _orderPayRepository.FindAsync(c => c.OrderId == input.OrderId);
            if(order == null || order.State != 1)
                return AppSrvResult();

            //处理钱包支付
            if (order.PayMode == (int)EnumPayMode.BALANCE || order.PayMode == (int)EnumPayMode.BONUS)
            {
                if (order.Amount > 0)
                {
                    var payresponse = await _userRpcService.WalletPay(new Adnc.Shared.RpcServices.Rtos.Usr.WalletPaymentRto()
                    {
                        UserId = order.UserId,
                        Amount = order.Amount,
                        OrderId = order.OrderId,
                        PaidMode = order.PayMode
                    });
                    if (!payresponse.IsSuccessStatusCode || !payresponse.Content)
                        throw new Exception("钱包支付失败");
                }

                order.State = 2;
                order.TradeTime = DateTime.Now;
                await _orderPayRepository.UpdateAsync(order, UpdatingProps<PaymentOrder>(x => x.State, x => x.TradeTime));

                //修改订单状态
                var changeEventId = IdGenerater.GetNextId();
                var changeEventData = new OrderStateChangeEvent.EventData() { OrderId = input.OrderId, ChangeTime = order.TradeTime.Value, ChangeType = 1 };
                var changeEventSource = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
                await _eventPublisher.PublishAsync(new OrderStateChangeEvent(changeEventId, changeEventData, changeEventSource));
            }
            return AppSrvResult();
        }

        /// <summary>
        /// 创建支付单
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<long>> CreateOrderPay(long userId, OrderPayCreateDto input)
        {
            //一个订单只有一个支付单
            var result = await _orderPayRepository.FindAsync(c => c.OrderId == input.OrderId);
            if (result != null)
                return result.Id;

            //订单超期时间
            int.TryParse(_config["WYT:PaymentTimeoutExpired"], out int Expired);
            var order = new PaymentOrder
            {
                Id = IdGenerater.GetNextId(),
                OrderId = input.OrderId,
                Amount = input.Amount,
                CreateTime = DateTime.Now,
                PayMode = input.PaidMode,
                UserId = userId,
                State = 1,
                ExpirationTime = DateTime.Now.AddSeconds(Expired == 0 ? 900 : Expired)  //超期时间默认15分钟
            };
            await _orderPayRepository.InsertAsync(order);
            return order.Id;
        }

        /// <summary>
        /// 支付单超期检查
        /// </summary>
        /// <returns></returns>
        public async Task<AppSrvResult> PaymentOrderTimeoutCheck()
        {
            var list = _orderPayRepository.Where(x => x.State == 1 && x.ExpirationTime <= DateTime.Now).ToList();
            foreach (var order in list)
            {
                order.State = -1;
                await _orderPayRepository.UpdateAsync(order, UpdatingProps<PaymentOrder>(x => x.State));

                //修改订单状态
                var changeEventId = IdGenerater.GetNextId();
                var changeEventData = new OrderStateChangeEvent.EventData() { OrderId = order.OrderId, ChangeTime = DateTime.Now, ChangeType = 2 };
                var changeEventSource = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
                await _eventPublisher.PublishAsync(new OrderStateChangeEvent(changeEventId, changeEventData, changeEventSource));
            }
            return AppSrvResult();
        }
    }
}
